/*
* Copyright 2010 Pavel Kozhin 
*
* Licensed under the Apache License, Version 2.0 (the "License"); 
* you may not use this file except in compliance with the License. 
* You may obtain a copy of the License at 
* 
* http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software 
* distributed  under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
* See the License for the specific language governing permissions and 
* limitations under the License.
*
* Author: Pavel Kozhin.
*/

package org.etherframework.metadata
{
	import org.etherframework.reflection.Accessor;
	import org.etherframework.reflection.Metadata;
	import org.etherframework.reflection.MetadataProperty;
	import org.etherframework.reflection.Method;
	import org.etherframework.reflection.Parameter;
	import org.etherframework.reflection.Variable;
	
	[ExcludeClass]
	public class MetadataParser
	{
		public function getMethods(xml:XML, metaName:String, isStatic:Boolean = false):Array 
		{
			var items:XMLList = (isStatic) ? xml.method : xml.factory.method;
			var result:Array = [];
			var parameters:Array;
			var metadata:Array;
			var method:Method;
			var methodItem:XML;
			items = items.metadata.(@name == metaName);
			
			for each (var item:XML in items) 
			{
				methodItem = item.parent();
				metadata = getMetaData(methodItem.metadata);
				parameters = getParameters(methodItem.parameter);
				method = new Method(methodItem.@name, methodItem.@returnType, methodItem.@uri, isStatic, parameters, metadata);
				result.push(method);
			}
			
			return result;
		}
		
		public function getAccessors(xml:XML, metaName:String, isStatic:Boolean = false):Array 
		{
			var items:XMLList = (isStatic) ? xml.accessor : xml.factory.accessor;
			var result:Array = [];
			var accessor:Accessor;
			var metadata:Array;
			var accessorItem:XML;
			var lastParent:XML;
			items = items.metadata.(@name == metaName);
			
			for each (var item:XML in items) 
			{
				accessorItem = item.parent();
				
				if  (accessorItem == lastParent)
					continue;
				
				lastParent = accessorItem;
				
				if (accessorItem.@access != Accessor.READ_WRITE)
					continue;
				
				metadata = getMetaData(accessorItem.metadata); 
				accessor = new Accessor(accessorItem.@name, accessorItem.@type, accessorItem.@uri, isStatic, accessorItem.@access, metadata);
				result.push(accessor);
			}
			return result;
		}
		
		public function getVariables(xml:XML, metaName:String, isStatic:Boolean = false):Array 
		{
			var result:Array = [];
			var items:XMLList = (isStatic) ? xml.variable : xml.factory.variable;
			var variable:Variable;
			var metadata:Array;
			var variableItem:XML;
			var lastParent:XML;
			items = items.metadata.(@name == metaName);
			
			for each (var item:XML in items) 
			{
				variableItem = item.parent();
				
				if  (variableItem == lastParent)
					continue;
				
				lastParent = variableItem;
				
				metadata = getMetaData(variableItem.metadata); 
				variable = new Variable(variableItem.@name, variableItem.@type, variableItem.@uri, isStatic, metadata);
				result.push(variable);
			}
			return result;
		}
		
		public function getClassMetaData(xml:XML, metaName:String):Array
		{
			var items:XMLList = xml.factory.metadata.(@name == metaName);
			var result:Array = getMetaData(items);
			
			return result;
		}
		
		private function getParameters(items:XMLList):Array 
		{
			var result:Array = [];
			var parameter:Parameter;
			
			for each(var item:XML in items) 
			{
				parameter = new Parameter(item.@index, item.@type, (item.@optional == "true"));
				result.push(parameter);
			}
		
			return result;
		}
		
		private function getMetaData(items:XMLList):Array 
		{
			var result:Array = [];
			var properties:Array;
			
			for each (var item:XML in items) 
			{
				if (item.@name.indexOf("__") == 0)
					continue;
				
				properties = [];
				for each (var metadataProperty:XML in item.arg) 
				{
					properties.push(new MetadataProperty(metadataProperty.@key, metadataProperty.@value));
				}
				result.push(new org.etherframework.reflection.Metadata(item.@name, properties));
			}
			return result;
		}

	}
}